package abel.wlmr.model.unit;

import java.util.ArrayList;
import java.util.List;

import abel.wlmr.model.WlmrBaseUnit;
import abel.wlmr.model.WlmrException;
import abel.wlmr.model.type.MeterConfigBody;
import io.netty.buffer.ByteBuf;

/**
 * B.5.4.1.3.25 F401： 终端水表档案配置
 * 数据单元格式见表 B.38。
 * 表B.38 终端水表档案配置数据单元格式
 * 
 * @author Abel
 *
 */
public class Afn04F401Unit extends WlmrBaseUnit {
    public static final short MIN_LENGTH = 2;

    private int meterCnt;

    private List<MeterConfigBody> meterList = new ArrayList<>();

    /**
     * 
     */
    public Afn04F401Unit() {
        super();
    }

    /**
     * @param guessedLen
     */
    public Afn04F401Unit(short guessedLen) {
        super(guessedLen);
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitPart#appendBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public ByteBuf appendBuf(ByteBuf buf) {
        if (meterList.size() != meterCnt) {
            throw new IllegalArgumentException(String
                .format("meter list should contains exact %s meters but size is %s.", meterCnt, meterList.size()));
        }

        buf.writeShortLE(meterCnt);
        for (MeterConfigBody m : meterList) {
            m.appendBuf(buf);
        }

        return buf;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitPart#parseBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public int parseBuf(ByteBuf buf) throws WlmrException {
        {
            ByteBuf alt = buf.duplicate();
            meterCnt = alt.readShortLE();
            if (alt.readableBytes() < meterCnt * new MeterConfigBody().getGuessedLength()) {
                return -1;
            }
        }

        // skip meter cnt.
        buf.skipBytes(2);

        meterList = new ArrayList<>();
        for (int i = 0; i < meterCnt; i++) {
            MeterConfigBody m = new MeterConfigBody();
            m.parseBuf(buf);

            meterList.add(m);
        }

        return getGuessedLength();
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return String.format("{meterCnt:%s, meterList:%s}", meterCnt, meterList);
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#getFinalLen()
     */
    @Override
    public short getFinalLen() {
        if (finalLen < 0) {
            finalLen = (short) (2 + meterCnt * MeterConfigBody.FIXED_LENGTH);
        }
        return finalLen;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.WlmrDataPart#getMinLength()
     */
    @Override
    public int getMinLength() {
        return MIN_LENGTH;
    }

    /**
     * @return the meterCnt
     */
    public int getMeterCnt() {
        return meterCnt;
    }

    /**
     * @param meterCnt
     *            the meterCnt to set
     */
    public void setMeterCnt(int meterCnt) {
        if (meterCnt < 0 || meterCnt > 2040) {
            throw new IllegalArgumentException("meter count should be [0,2040] but: " + meterCnt);
        }
        this.meterCnt = meterCnt;
    }

    /**
     * @return the meterList
     */
    public List<MeterConfigBody> getMeterList() {
        return meterList;
    }

    /**
     * @param meterList
     *            the meterList to set
     */
    public void setMeterList(List<MeterConfigBody> meterList) {
        if (meterList == null) {
            throw new IllegalArgumentException("meter list can't be null");
        }
        for (MeterConfigBody m : meterList) {
            if (m == null) {
                throw new IllegalArgumentException("none of meter list should be null");
            }
        }

        this.meterList = meterList;
    }

}
